package com.bjy.qa.service.functionaltest.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.bjy.qa.dao.functionaltest.ReviewTestCaseDao;
import com.bjy.qa.dao.functionaltest.ReviewsDao;
import com.bjy.qa.dao.functionaltest.ReviewsResultDao;
import com.bjy.qa.dao.functionaltest.ReviewsUserDao;
import com.bjy.qa.entity.MyPage;
import com.bjy.qa.entity.ResponsePagingData;
import com.bjy.qa.entity.functionaltest.*;
import com.bjy.qa.entity.user.User;
import com.bjy.qa.enumtype.EditStatus;
import com.bjy.qa.service.functionaltest.IReviewsService;
import com.bjy.qa.util.security.SecurityUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

@Service
public class ReviewsService extends ServiceImpl<ReviewsDao, Reviews> implements IReviewsService{

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    ReviewsDao reviewsDao;

    @Resource
    ReviewsUserService reviewsUserService;

    @Resource
    ReviewTestCaseService reviewTestCaseService;

    @Resource
    ReviewsUserDao reviewsUserDao;

    @Resource
    ReviewTestCaseDao reviewTestCaseDao;

    @Resource
    ReviewsResultDao reviewsResultDao;

    @Override
    public ResponsePagingData list(MyPage<Reviews> myPage) {
        Page<Reviews> page = new Page(myPage.getPageNum(), myPage.getPageSize()); // 构造待查询 page 对象
        page.setOrders(OrderItem.descs("id")); // 按照id倒序排
        // 构造待查询
        Reviews reviews = myPage.getQuery();
        QueryWrapper<Reviews> queryWrapper = new QueryWrapper<>();
        if (reviews != null) {
            if (StringUtils.isNotBlank(reviews.getProjectId().toString())) {
                queryWrapper.eq("project_id", reviews.getProjectId());
            }
            if (StringUtils.isNotBlank(reviews.getName())) {
                queryWrapper.like("name", reviews.getName());
            }
        }
        page = reviewsDao.selectPage(page, queryWrapper);

        myPage.setTotalRecords(page.getTotal()); // 设置返回总记录数

        return new ResponsePagingData(myPage, page.getRecords());
    }

    @Override
    public int add(Reviews reviews){
        reviews.setStatus(EditStatus.WAIT_REVIEW.getValue());
        reviews.setInitiatorUserId(SecurityUtils.getCurrentUserId());
        if (reviews.getUser() != null) {
            reviews.setTotalReviewers(reviews.getUser().size());
        }
        int result = reviewsDao.insert(reviews);  //先插入一条数据，生成 reviews id

        Long reviewsId = reviews.getId();
        List<User> user = reviews.getUser();
        if (user != null && user.size() != 0) { // 保存reviews user映射关系
            List<ReviewsUser> reviewsUserList = new LinkedList<>();
            for (int i = 0; i < user.size(); i++) {
                ReviewsUser reviewsUser = new ReviewsUser();
                reviewsUser.setReviewsId(reviewsId);
                reviewsUser.setReviewerUserId(user.get(i).getId());
                reviewsUser.setProjectId(reviews.getProjectId());
                reviewsUserList.add(reviewsUser);
            }
            // 批量操作数据库
            reviewsUserService.saveBatch(reviewsUserList);
        }

        return result;
    }

    @Override
    public int update(Reviews reviews) {
        reviews.setUpdatedAt(null);
        reviews.setCreatedAt(null);

        List<User> user = reviews.getUser();
        List<TestCase> testCases = reviews.getTestCases();
        Long reviewsId = reviews.getId();

        if (user != null) {
            // 根据 reviewsId, projectId 一次性删除所有旧的ReviewsUser
            QueryWrapper<ReviewsUser> deleteWrapper = new QueryWrapper<>();
            deleteWrapper.eq("reviews_id", reviewsId);
            deleteWrapper.eq("project_id", reviews.getProjectId());
            reviewsUserDao.delete(deleteWrapper);

            List<ReviewsUser> reviewsUserList = new ArrayList<>(); // 添加新的 ReviewsUser
            for (User u : user) {
                ReviewsUser reviewsUser = new ReviewsUser();
                reviewsUser.setReviewsId(reviewsId);
                reviewsUser.setReviewerUserId(u.getId());
                reviewsUser.setProjectId(reviews.getProjectId());
                reviewsUserList.add(reviewsUser);
            }
            reviewsUserService.saveBatch(reviewsUserList);
        }

        if (testCases != null ) {
            List<ReviewTestCase> reviewTestCaseList = new ArrayList<>();

            for (int i = 0; i < testCases.size(); i++) {
                ReviewTestCase reviewTestCase = new ReviewTestCase();
                reviewTestCase.setReviewsId(reviewsId);
                reviewTestCase.setTestCaseId(testCases.get(i).getId());
                reviewTestCase.setProjectId(testCases.get(i).getProjectId());
                reviewTestCaseList.add(reviewTestCase);
            }
            List<ReviewTestCase> originReviewTestCaseList = reviewTestCaseDao.selectByReviewId(reviewsId);

            if (originReviewTestCaseList.size() == 0) { // 旧的为空，则直接插入新的
                reviewTestCaseService.saveBatch(reviewTestCaseList);
            } else if (reviewTestCaseList.size() == 0) { // testCases 为空，则删除所有旧的
                reviewTestCaseService.removeBatchByIds(originReviewTestCaseList);

                // 删除所有旧的评审结果
                QueryWrapper<ReviewsResult> queryReviewsResultWrapper = new QueryWrapper<>();
                queryReviewsResultWrapper.eq("project_id", reviews.getProjectId());
                queryReviewsResultWrapper.eq("reviews_id", reviewsId);
                reviewsResultDao.delete(queryReviewsResultWrapper);
            } else { // 有部分用例被删除
                reviewTestCaseService.removeBatchByIds(getNotIncludeList(originReviewTestCaseList, reviewTestCaseList));
                reviewTestCaseService.saveBatch(getNotIncludeList(reviewTestCaseList, originReviewTestCaseList));

                // 删除用例对应的评审结果
                List<Long> deleteReviewsTestCaseList = new ArrayList<>();
                for (ReviewTestCase reviewTestCase : getNotIncludeList(originReviewTestCaseList, reviewTestCaseList)) {
                    deleteReviewsTestCaseList.add(reviewTestCase.getTestCaseId());
                }
                if (deleteReviewsTestCaseList.size() > 0) {
                    QueryWrapper<ReviewsResult> queryReviewsResultWrapper = new QueryWrapper<>();
                    queryReviewsResultWrapper.eq("project_id", reviews.getProjectId());
                    queryReviewsResultWrapper.eq("reviews_id", reviewsId);
                    queryReviewsResultWrapper.in("test_case_id", deleteReviewsTestCaseList);
                    reviewsResultDao.delete(queryReviewsResultWrapper);
                }
            }

            reviews.setTotalTestCase(reviewTestCaseList.size()); // 设置评审计划表中的 用例总数
        }

        // 设置评审计划表中的 通过率 和 通过用例数
        QueryWrapper<ReviewsResult> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("project_id", reviews.getProjectId());
        queryWrapper.eq("reviews_id", reviewsId);
        queryWrapper.eq("status", EditStatus.FINISH.getValue());
        reviews.setPassTestCases(reviewsResultDao.selectCount(queryWrapper).intValue());
        reviews.setPassRate(((Double) ((double) reviews.getPassTestCases() / (double) reviews.getTotalTestCase() * 100)).intValue());

        // 设置评审计划表中的 评审人数
        if (reviews.getUser() != null) {
            reviews.setTotalReviewers(reviews.getUser().size());
        }
        return reviewsDao.updateById(reviews);
    }

    @Override
    public int delete(Long id) {
        return reviewsDao.deleteById(id);
    }

    public Reviews findById(Long id) {
        Reviews reviews = reviewsDao.selectById(id);
        List<User> users = reviewsUserDao.findByReviewId(id);
        List<TestCase> testCases = reviewTestCaseDao.findByReviewId(id);
        reviews.setUser(users);
        reviews.setTestCases(testCases);
        return reviews;
    }

    @Override
    public Object stop(Long id) {
        Reviews reviews = reviewsDao.selectById(id);
        reviews.setStatus(EditStatus.FINISH.getValue());
        reviewsDao.updateById(reviews);
        return "结束评审成功！";
    }

    /*
     *  遍历 originList,将不在 comparedList 中的元素添加到 notIncludeList
     */
    private List<ReviewTestCase> getNotIncludeList(List<ReviewTestCase> originList, List<ReviewTestCase> comparedList) {
        List<ReviewTestCase> notIncludeList = new ArrayList<>();
        for (int i = 0; i < originList.size(); i++) {
            boolean exist = false;
            for (ReviewTestCase reviewTestCase : comparedList) {
                if (originList.get(i).getTestCaseId().equals(reviewTestCase.getTestCaseId())) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                notIncludeList.add(originList.get(i));
            }
        }
        return notIncludeList;
    }

}
